package com.code.wflow.service.impl;

import com.code.wflow.common.Constants;
import com.code.wflow.constants.InstanceStage;
import com.code.wflow.constants.InstanceStatus;
import com.code.wflow.constants.TaskFinishEnum;
import com.code.wflow.handler.InstanceActuator;
import com.code.wflow.mapper.InstanceMapper;
import com.code.wflow.mapper.InstanceNodeDetailMapper;
import com.code.wflow.mapper.InstanceNodeMapper;
import com.code.wflow.mapper.WorkflowTaskMapper;
import com.code.wflow.model.Instance;
import com.code.wflow.model.InstanceNode;
import com.code.wflow.model.InstanceNodeDetail;
import com.code.wflow.model.WorkflowTask;
import com.code.wflow.service.InstanceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 流程实例表(WorkflowInstance)表服务层
 *
 * @author ggh
 * @date 2022/10/26
 */
@Service
public class InstanceServiceImpl implements InstanceService {
    @Autowired
    private InstanceMapper instanceMapper;
    @Autowired
    private InstanceNodeMapper instanceNodeMapper;
    @Autowired
    private InstanceNodeDetailMapper instanceNodeDetailMapper;
    @Autowired
    private WorkflowTaskMapper workflowTaskMapper;
    @Autowired
    private InstanceActuator instanceActuator;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Instance queryById(Long id) {
        return this.instanceMapper.queryById(id);
    }


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Instance queryDetailById(Long id) {
        return this.instanceMapper.queryDetailById(id);
    }

    /**
     * 通过流程id查询集合数据
     *
     * @param workflowId 主键
     * @return 实例对象
     */
    @Override
    public List<Instance> queryByWorkflowId(Long workflowId) {
        return this.instanceMapper.queryByWorkflowId(workflowId);
    }


    /**
     * 通过流程id查询集合数据
     *
     * @param idList 主键
     * @return 实例对象
     */
    @Override
    public List<Instance> queryDetailByIdList(List<Long> idList) {
        return this.instanceMapper.queryDetailByIdList(idList);
    }

    /**
     * 通过流程id查询集合数据
     *
     * @param workflowId 主键
     * @return 实例对象
     */
    @Override
    public List<Instance> queryByWorkflowIdAndStatus(Long workflowId, Byte status) {
        return this.instanceMapper.queryByWorkflowIdAndStatus(workflowId, status);
    }

    /**
     * 查询指定行数据
     *
     * @param userId  用户id
     * @param status  状态
     * @param keyword 关键字
     * @return
     */
    @Override
    public List<Instance> queryByConditions(Long userId, Byte status, String keyword) {
        return this.instanceMapper.queryByConditions(userId, status, keyword);
    }

    /**
     * 执行流程
     *
     * @param instanceId
     * @param taskList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean performInstance(Long instanceId, List<WorkflowTask> taskList, List<InstanceNode> instanceNodeList, Boolean isFinish) {
        if (!CollectionUtils.isEmpty(taskList) && workflowTaskMapper.insertList(taskList) != taskList.size()) {
            throw new RuntimeException();
        }
        if (!CollectionUtils.isEmpty(instanceNodeList) && instanceNodeMapper.updateStage(instanceNodeList) != instanceNodeList.size()) {
            throw new RuntimeException();
        }

        if (!isFinish && instanceMapper.updateStageAndStatus(instanceId, InstanceStage.PROGRESSING.getVal(), null, null) <= 0) {
            throw new RuntimeException();
        }
        if (isFinish && this.instanceMapper.updateStageAndStatus(instanceId, InstanceStage.END.getVal(), InstanceStatus.APPROVAL.getVal(), new Date()) <= 0) {
            throw new RuntimeException();
        }
        return true;
    }


    /**
     * 撤销流程
     *
     * @param instance
     * @param taskIdList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean revokeInstance(Instance instance, List<Long> taskIdList) {
        if (instanceMapper.updateStageAndStatus(instance.getId(), InstanceStage.END.getVal(), InstanceStatus.REVOKE.getVal(), new Date()) <= 0) {
            return false;
        }
        if (!CollectionUtils.isEmpty(taskIdList) && workflowTaskMapper.updateTaskFinish(taskIdList, TaskFinishEnum.TRUE.isFinish()) != taskIdList.size()) {
            throw new RuntimeException();
        }
        return true;
    }


    /**
     * 发起流程
     *
     * @param instance
     * @param instanceNodeList
     * @param instanceNodeDetailList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean start(Instance instance, List<InstanceNode> instanceNodeList, List<InstanceNodeDetail> instanceNodeDetailList) {
        if (this.instanceMapper.insert(instance) <= 0) {
            return false;
        }
        if (this.instanceNodeMapper.insertList(instance.getId(), instanceNodeList) != instanceNodeList.size()) {
            throw new RuntimeException();
        }
        Map<Long, InstanceNode> instanceNodeMap = instanceNodeList.stream().collect(Collectors.toMap(InstanceNode::getWorkflowNodeId, Function.identity()));
        for (InstanceNodeDetail instanceNodeDetail : instanceNodeDetailList) {
            instanceNodeDetail.setInstanceNodeId(instanceNodeMap.get(instanceNodeDetail.getWorkflowNodeId()).getId());
        }
        if (this.instanceNodeDetailMapper.insertList(instance.getId(), instanceNodeDetailList) != instanceNodeDetailList.size()) {
            throw new RuntimeException();
        }

        if (!instanceActuator.performNextInstance(instance.getId(), Constants.ROOT_LEVEL - 1, Constants.NULL_CONDITION_LEVEL)) {
            throw new RuntimeException();
        }
        return true;
    }

    /**
     * 修改数据
     *
     * @param workflowInstance 实例对象
     * @return 实例对象
     */
    @Override
    public boolean update(Instance workflowInstance) {
        return this.instanceMapper.update(workflowInstance) > 0;
    }

    /**
     * 更新流程阶段和状态
     *
     * @param instanceId
     * @param stage
     * @param status
     * @return
     */
    @Override
    public boolean updateStageAndStatus(Long instanceId, Byte stage, Byte status, Date date) {
        return this.instanceMapper.updateStageAndStatus(instanceId, stage, status, date) > 0;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        return this.instanceMapper.deleteById(id) > 0;
    }

    /**
     * 通过主键删除数据
     *
     * @param idList 主键
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIdList(List<Long> idList) {
        if (this.instanceMapper.deleteByIdList(idList) == idList.size()) {
            return true;
        }
        throw new RuntimeException();
    }
}
